/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ************************************************************************************************
 * @file     Xspi_Bus.h                                                                           *
 * @brief    This file contains interface header for xSPI BUS  driver, ...                          *
 * @author   Department/Semidrive                                                                     *
 * @date     2025/02/26                                                              *
 *                                                                                                 *
 **************************************************************************************************/

#ifndef XSPI_BUS_H
#define XSPI_BUS_H

#include <debug.h>
#include "lld_platform.h"
#include "Xspi_Ip.h"

#ifdef __cplusplus
extern "C" {
#endif

#define XSPI_BUS_NAME_BUF_SIZE  (32u)
#define XSPI_BUS_MAX_ID_LEN     (6u)
#define XSPI_BUS_MAX_CS_NUM     (2u)

#define XSPI_BUS_SECTOR_4KB_TYPE             (0)    /* Size XSPI_BIT(12) */
#define XSPI_BUS_SECTOR_32KB_TYPE            (1)    /* Size XSPI_BIT(15) */
#define XSPI_BUS_SECTOR_64KB_TYPE            (2)    /* Size XSPI_BIT(16) */
#define XSPI_BUS_SECTOR_128KB_TYPE           (3)    /* Size XSPI_BIT(17) */
#define XSPI_BUS_SECTOR_256KB_TYPE           (4)    /* Size XSPI_BIT(18) */
#define XSPI_BUS_SECTOR_TYPE_MAX             (5)
#define XSPI_BUS_SECTOR_TYPE_TO_POST(type) (12 + ((XSPI_BUS_SECTOR_4KB_TYPE == (type)) ? 0 : 2) + (type))
#define XSPI_BUS_SECTOR_TYPE_TO_SIZE(type) XSPI_BIT(XSPI_BUS_SECTOR_TYPE_TO_POST(type))


#define XSPI_BUS_PROTO_1S_0S_1S \
    XSPI_IP_X_0_X_PROTO(XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_2S_0S_2S \
    XSPI_IP_X_0_X_PROTO(XSPI_IP_DUAL_LANS, XSPI_IP_SDR, XSPI_IP_DUAL_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_4S_0S_4S \
    XSPI_IP_X_0_X_PROTO(XSPI_IP_QUAD_LANS, XSPI_IP_SDR, XSPI_IP_QUAD_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_8D_0D_8D \
    XSPI_IP_X_0_X_PROTO(XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, 0u)
#define XSPI_BUS_PROTO_8D_0D_8D_INVERT \
    XSPI_IP_X_0_X_PROTO(XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, 1u)

#define XSPI_BUS_PROTO_1S_1S_1S \
    XSPI_IP_PROTO(XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_2S_2S_2S \
    XSPI_IP_PROTO(XSPI_IP_DUAL_LANS, XSPI_IP_SDR, XSPI_IP_DUAL_LANS, XSPI_IP_SDR, XSPI_IP_DUAL_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_4S_4S_4S \
    XSPI_IP_PROTO(XSPI_IP_QUAD_LANS, XSPI_IP_SDR, XSPI_IP_QUAD_LANS, XSPI_IP_SDR, XSPI_IP_QUAD_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_1S_1S_4S \
    XSPI_IP_PROTO(XSPI_IP_QUAD_LANS, XSPI_IP_SDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_1S_4D_4D \
    XSPI_IP_PROTO(XSPI_IP_QUAD_LANS, XSPI_IP_DDR, XSPI_IP_QUAD_LANS, XSPI_IP_DDR, XSPI_IP_SINGLE_LANS, XSPI_IP_SDR, 0u)
#define XSPI_BUS_PROTO_8D_8D_8D \
    XSPI_IP_PROTO(XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, 0u)
#define XSPI_BUS_PROTO_8D_8D_8D_INVERT \
    XSPI_IP_PROTO(XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, XSPI_IP_OCTAL_LANS, XSPI_IP_DDR, 1u)

/* 1x-1x-1x 2x-2x-2x 4x-4x-4x 8x-8x-8x */
#define XSPI_BUS_REG_PROTO(lans, rate, invertOpcodeEn) \
    XSPI_IP_PROTO(lans, rate, lans, rate, lans, rate, invertOpcodeEn)

typedef struct {
    uint8_t csNum;
    bool swResetEn;
    bool xipEnable;
} Xspi_BusConfigType;

struct Xspi_BusHandle;
typedef struct {
    /* Static configuration */
    const uint8_t name[XSPI_BUS_NAME_BUF_SIZE];
    uint8_t flashId[XSPI_BUS_MAX_ID_LEN];
    Xspi_IpProtoType readProto;
    Xspi_IpProtoType writeProto;
    uint8_t eraseOpcode[XSPI_BUS_SECTOR_TYPE_MAX];
    uint8_t readDummy;
    uint8_t writeDummy;
    uint8_t statusDummy;
    uint32_t pageSize;
    /* Operation callback */
    int32_t (*defaultInit)(struct Xspi_BusHandle *bus, uint8_t cs);
    int32_t (*getBankStatus)(struct Xspi_BusHandle *bus, uint8_t cs, uint32_t addr, uint32_t length);
    int32_t (*setProtectArea)(struct Xspi_BusHandle *bus, uint8_t cs, uint32_t addr, uint32_t length);
    int32_t (*enterXipMode)(struct Xspi_BusHandle *bus, uint8_t cs, bool enable);
} Xspi_BusDeviceInfoType;

typedef struct {
    /* Static configuration */
    Xspi_BusDeviceInfoType info;
    /* Dynamic parameter */
    uint32_t size;
    uint8_t cs;
    uint8_t addrWidth;
    uint32_t offset;
    Xspi_IpProtoType regProto;
    uint32_t sectorSize;
} Xspi_BusDeviceType;

typedef struct Xspi_BusHandle {
    Xspi_BusDeviceType device[XSPI_BUS_MAX_CS_NUM];
    uint8_t csNum;
    uint32_t totalSize;
    Xspi_IpHostType *host;

    /* Runtiming */
} Xspi_BusHandleType;

int32_t Xspi_BusInit(Xspi_BusHandleType *bus, Xspi_IpHostType *host, const Xspi_BusConfigType *busConfig);
int32_t Xspi_BusDeInit(Xspi_BusHandleType *bus);

int32_t Xspi_BusRead(Xspi_BusHandleType *bus, uint32_t address, uint8_t* buf, uint32_t size);

int32_t Xspi_BusWrite(Xspi_BusHandleType *bus, uint32_t address, const uint8_t* buf, uint32_t size);
int32_t Xspi_BusWriteSync(Xspi_BusHandleType *bus, uint32_t address, const uint8_t* buf, uint32_t size);

int32_t Xspi_BusSectorErase(Xspi_BusHandleType *bus, uint32_t address, uint32_t size, uint32_t *eraseSize);
int32_t Xspi_BusSectorEraseSync(Xspi_BusHandleType *bus, uint32_t address, uint32_t size, uint32_t *eraseSize);
int32_t Xspi_BusErase(Xspi_BusHandleType *bus, uint32_t address, uint32_t size);
int32_t Xspi_BusEraseSync(Xspi_BusHandleType *bus, uint32_t address, uint32_t size);

int32_t Xspi_BusGetStatus(Xspi_BusHandleType *bus);
int32_t Xspi_BusGetBlockStatus(Xspi_BusHandleType *bus, uint32_t address, uint32_t size);

int32_t Xspi_BusSetProtectArea(Xspi_BusHandleType *bus, uint32_t addr, uint32_t size);

int32_t Xspi_BusGetProtectStatus(Xspi_BusHandleType *bus, uint32_t addr, uint32_t size);

int32_t Xspi_BusCancel(Xspi_BusHandleType *bus);

#ifdef __cplusplus
}
#endif
#endif /* XSPI_BUS_H */


/* End of file */
